package fuzzylizard.teamdocs.web;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import fuzzylizard.teamdocs.Constants;

import wicket.PageParameters;
import wicket.markup.html.basic.Label;
import wicket.markup.html.form.Form;
import wicket.markup.html.form.upload.FileUpload;
import wicket.markup.html.form.upload.FileUploadField;
import wicket.markup.html.link.Link;
import wicket.markup.html.list.ListItem;
import wicket.markup.html.list.ListView;
import wicket.markup.html.panel.FeedbackPanel;
import wicket.util.file.Files;
import wicket.util.file.Folder;
import wicket.util.lang.Bytes;

public class UploadPage extends TeamdocsPage {

    private static final Log Log = LogFactory.getLog(UploadPage.class);

    private List<File> files = new ArrayList<File>();

    private FileListView fileListView;

    private Folder uploadFolder;

    /**
     * Constructor.
     * 
     * @param parameters
     *            Page parameters
     */
    public UploadPage(final PageParameters parameters) {
        setupUploadFolder();

        add(new FeedbackPanel("uploadFeedback"));

        add(new FileUploadForm("simpleUpload"));

        add(new Label("dir", uploadFolder.getName()));
        files.addAll(Arrays.asList(uploadFolder.listFiles()));
        fileListView = new FileListView("fileList", files);
        add(fileListView);
    }

    private void setupUploadFolder() {
        uploadFolder = new Folder(System.getProperty("java.io.tmpdir"), "wicket-uploads");
        uploadFolder.mkdirs();
        Log.debug("Upload directory = " + String.valueOf(uploadFolder));
    }

    /**
     * Refresh file list.
     */
    private void refreshFileList() {
        fileListView.modelChanging();
        files.clear();
        files.addAll(Arrays.asList(uploadFolder.listFiles()));
    }

    /**
     * Check whether the file allready exists, and if so, try to delete it.
     * 
     * @param newFile
     *            the file to check
     */
    private boolean fileExists(File newFile) {
        if (newFile.exists()) {
            addFeedback("ERROR: File " + newFile + " already exists");
            return true;
        }
        return false;
    }

    private void addFeedback(String message) {
        UploadPage.this.info(message);
    }

    /**
     * Form for uploads.
     */
    private class FileUploadForm extends Form {

        private FileUploadField fileUploadField;

        /**
         * Construct.
         * 
         * @param name Component name
         */
        public FileUploadForm(String name) {
            super(name);
            setMultiPart(true);
            add(fileUploadField = new FileUploadField("fileInput"));
            setMaxSize(Bytes.megabytes(Constants.MAX_UPLOAD_SIZE));
        }

        /**
         * @see wicket.markup.html.form.Form#onSubmit()
         */
        protected void onSubmit() {
            final FileUpload upload = fileUploadField.getFileUpload();
            if (upload != null) {
                File newFile = createFile(upload);
                if (!fileExists(newFile)) {
                    saveFile(upload, newFile);
                    refreshFileList();
                }
            }
        }

        private File createFile(final FileUpload upload) {
            return new File(uploadFolder, upload.getClientFileName());
        }

        private void saveFile(final FileUpload upload, File newFile) {
            try {
                newFile.createNewFile();
                upload.writeTo(newFile);
                addFeedback("saved file: " + upload.getClientFileName());
            } catch (IOException e) {
                throw new IllegalStateException("Unable to write file");
            }
        }
    }

    /**
     * List view for files in upload folder.
     */
    private class FileListView extends ListView {
        /**
         * Constructor
         * 
         * @param name
         *            Component name
         * @param files
         *            The file list model
         */
        public FileListView(String name, final List<File> files) {
            super(name, files);
        }

        /**
         * @see ListView#populateItem(ListItem)
         */
        protected void populateItem(ListItem listItem) {
            final File file = (File) listItem.getModelObject();
            listItem.add(new Label("file", file.getName()));
            listItem.add(new Link("delete") {
                public void onClick() {
                    Files.remove(file);
                    refreshFileList();
                    addFeedback("Deleted " + file);
                }
            });
        }
    }
}
